package q990

import "fmt"

var m map[string]*chrEqNeq

type chrEqNeq struct {
	chr string
	eq  []string
	neq []string
}

func (n *chrEqNeq) appendEqMulti(chr string) {
	for _, item := range n.eq {
		m[item].appendEq(chr)
	}
	n.appendEq(chr)
	for _, item := range m[chr].eq {
		n.appendEq(item)
	}
}

func (n *chrEqNeq) appendNeqMulti(chr string) {
	for _, item := range n.eq {
		m[item].appendNeq(chr)
	}
	n.appendNeq(chr)
	for _, item := range m[chr].eq {
		n.appendNeq(item)
	}
}

func (n *chrEqNeq) appendEq(chr string) {
	for _, item := range n.eq {
		if item == chr {
			return
		}
	}
	n.eq = append(n.eq, chr)
}

func (n *chrEqNeq) appendNeq(chr string) {
	for _, item := range n.neq {
		if item == chr {
			return
		}
	}
	n.neq = append(n.neq, chr)
}

func (n *chrEqNeq) checkCorrect() bool {
	for _, chr := range n.eq {
		for _, chr1 := range n.neq {
			if chr1 == chr {
				return false
			}
		}
	}
	return true
}

func equationsPossible(equations []string) bool {

	m = map[string]*chrEqNeq{}

	for _, str := range equations {
		a := str[0:1]
		eq := str[1:2]
		b := str[3:4]

		_, aExists := m[a]
		_, bExists := m[b]

		if !aExists {
			m[a] = &chrEqNeq{chr: a, eq: []string{}, neq: []string{}}
		}
		if !bExists {
			m[b] = &chrEqNeq{chr: b, eq: []string{}, neq: []string{}}
		}
		p(str)
		if eq == "=" && a == b {
			continue
		} else if eq == "!" && a == b {
			return false
		} else if eq == "=" {
			m[a].appendEqMulti(b)
			m[b].appendEqMulti(a)
		} else {
			m[a].appendNeqMulti(b)
			m[b].appendNeqMulti(a)
		}
		p("")
		if !m[a].checkCorrect() {
			return false
		}
		if !m[b].checkCorrect() {
			return false
		}
	}

	for _, item := range m {
		if !item.checkCorrect() {
			return false
		}
	}

	return true
}

func p(tag string) {
	return
	fmt.Println("----------------", tag)
	for k, item := range m {
		fmt.Println(k, ":", item.chr, item.eq, item.neq)
	}
}
